package me.shep.wishlist.server;

import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;

import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import me.shep.wishlist.client.DesiredItem;
import me.shep.wishlist.client.Person;
import me.shep.wishlist.client.RPC.InventoryService;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.ibatis.sqlmap.client.SqlMapClient;

//change SQLException to Exception to print stack traces for all exceptions...
public class InventoryServiceImpl extends RemoteServiceServlet implements InventoryService {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private void cleanPeople(List<Person> l, Person user) {
		//Done inefficiently, but meh
		//System.out.println("cleanPeople Called... " + user);
		for (Person i : l) {
			//System.out.println("debug1 "+i.getEmail()+" this users email: " + user.getEmail());
			if(i.getId() == user.getId()) {
			//if (i.getEmail().equals(email)) {
				//System.out.println(i.getEmail());
				
				//Use iterator here or else you get a java.util.ConcurrentModificationException
				Iterator<DesiredItem> iter = i.getDesiredItems().iterator();
				while(iter.hasNext()) {
					DesiredItem d = iter.next();
					if(!d.wanterCanSee) {
						//System.out.println("removing " +i.getName() + d.getName());
						iter.remove();
					}
					else
						d.setWhoPurchasedIt(null);
				}
				/*for (DesiredItem d : i.getDesiredItems()) {
					System.out.println("wanter can see? " + d.getName() + d.wanterCanSee);
					if(!d.wanterCanSee) {
						System.out.println("removing " +i.getName() + d.getName());
						i.getDesiredItems().remove(d);
					}
					else
						d.setWhoPurchasedIt(null);
					
				}*/
			}
		}
		//return l;
	}
	
	private String useToken(String token) throws Exception{
		HttpClient httpclient = new DefaultHttpClient();
		HttpGet httpGet = new HttpGet("http://www.google.com/m8/feeds/contacts/default/thin?max-results=0");
		httpGet.setHeader("Authorization", "AuthSub token="+token);
		String xml = EntityUtils.toString(httpclient.execute(httpGet).getEntity());
		
	    //System.out.println("Server Response:" + xml);
		
		try {
			return xml.substring(xml.indexOf("<email>")+7, xml.indexOf("</email>"));
		}
		catch (Exception e) {
			return null;
		} 
		//return "cwshep@gmail.com";
	}
	//maybe this should return a person?  that way we have id, name, email... etc
	public Person validate(String token) {
		//TODO: Server side expiry
		try {
			//First check to see if they already have a valid session
			List<Person> validate = SqlMapManager.getSqlMapClient().queryForList("validate", token);
			//System.out.println(validate.size() + " tokens matched the validate query.");
			if (validate.size() == 1) {
				return validate.get(0);
			}
			else if (validate.size() > 1)
				throw new RuntimeException(validate.size() + " have the same token!!!! User1: " + validate.get(0).getEmail() + ", token: " + token);  //make database unique?
			else
				throw new RuntimeException("User not logged in!");  //make database unique?
		}
		catch (SQLException e){
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);	
		}
	}
	
	public Person login(String token) throws Exception {
		try {
			//First check to see if they already have a valid session
			List<Person> validate = SqlMapManager.getSqlMapClient().queryForList("validate", token);
			//System.out.println(validate.size() + " tokens matched the validate query.");
			if (validate.size() == 1) {
				return validate.get(0);
			}
			else if (validate.size() > 1)
				throw new RuntimeException(validate.size() + " have the same token!!!! User1: " + validate.get(0).getEmail() + ", token: " + token);  //make database unique?	
			
			String user = useToken(token);
			if (user == null)
				throw new RuntimeException("Error, the token provided did not exist and did not work with google.");
		
			Person p = new Person();
			p.setEmail(user);  //TODO:  retrieve this login from the server...
			p.setToken(token);
		
			SqlMapManager.getSqlMapClient().update("login", p);
			
			return validate(token);
		}
		catch (SQLException e){
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);	
		}
		
	}
	
	public void logout(String token){
		try {
			SqlMapManager.getSqlMapClient().update("logout", token);
		}
		catch (SQLException e){
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);	
		}
	}
	
	public List<Person> getPeople(String token)  throws Exception {
		Person user = validate(token);
		if(user == null)
			throw new RuntimeException("Error, not logged in!");  //TODO: custom exceptions
		//TODO: Filter results so that user can't see hidden items (either in java or in sql)
		try {
		SqlMapClient client = SqlMapManager.getSqlMapClient();
			
			List<Person> l = client.queryForList("getPeople");
			cleanPeople(l, user);
			//System.out.println(l.get(0).getEmail() + l.get(0).getDesiredItems().size() + l.get(0).getEmail() + l.size());
			return l;
		} 
		catch (Exception e){
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);	
		}
	}
	public void updateItem(DesiredItem d, String token) throws Exception {
		SqlMapClient client = SqlMapManager.getSqlMapClient();
		try {	
			client.update("updateItemByID", d);
		} 
		catch (SQLException e){
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);	
		}
	}
	public void deleteItem(int id, String token) throws Exception {
		Person user = validate(token);
		//TODO: get the item by id, check to see if the person either added it or wants it, if not then throw exception...
		
		SqlMapClient client = SqlMapManager.getSqlMapClient();
		try {	
			client.delete("deleteItemByID", id);
		} 
		catch (SQLException e){
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);	
		}
	}
	public void addItem(DesiredItem d, String token) throws Exception {
		Person user = validate(token);
		//d.setWhoAddedIt(user.getEmail());
		d.setWhoAddedIt(String.valueOf(user.getId()));
		if (d.whoPurchasedIt != null)
			d.setWhoPurchasedIt(String.valueOf(user.getId()));
		//System.out.println("Adding item: "+d.getName()+d.getDescription()+d.getWhoAddedIt()+d.getWhoWantsIt());
		SqlMapClient client = SqlMapManager.getSqlMapClient();
		try {	
			client.insert("addItem", d);
		} 
		catch (Exception e){
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);
		}
	}
	
	public void purchaseItem(int id, String token) {
		Person user = validate(token);
		DesiredItem d = new DesiredItem();
		d.setId(id);
		d.setWhoPurchasedIt(String.valueOf(user.getId()));
		SqlMapClient client = SqlMapManager.getSqlMapClient();
		try {	
			client.update("purchaseItem", d);
		} 
		catch (Exception e){
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);
		}
	}
}
